package helper

import (
	"context"
	"fmt"

	"gorm.io/gorm"
)

const (
	DefaultPage  = 1
	DefaultLimit = 10
)

// SqlBuilder sql生成器 简单版
type SqlBuilder struct {
	Field      string        // 查询字段 如：*
	Where      string        // where语句 如：id=? and xxx in (?)
	WhereParam []interface{} // where 绑定参数
	Order      string        // 排序 如：id asc
	Group      string        // group by
	Limit      int           // 分页设置 10
	Page       int           // 第几页 1
	IsPage     bool          // 是否分页
	DB         *gorm.DB
}

// GetPage 获取第几页
func (s *SqlBuilder) GetPage() int {

	if s.Page <= 0 {
		s.Page = DefaultPage
	}

	return s.Page
}

// GetLimit 获取分页设置
func (s *SqlBuilder) GetLimit() int {
	if s.Limit <= 0 {
		s.Limit = DefaultLimit
	}
	return s.Limit
}

// GetOffset 获取offset
func (s *SqlBuilder) GetOffset() int {
	limit := s.GetLimit()
	page := s.GetPage()
	return (page - 1) * limit
}

// Build 生成
func (s *SqlBuilder) Build() {
	db := s.DB
	// 设置字段
	if s.Field != "" {
		db = db.Select(s.Field)
	}

	// sql类型的查询
	if s.Where != "" {
		db = db.Where(s.Where, s.WhereParam...)
	}

	if s.Order != "" {
		db = db.Order(s.Order)
	}

	if s.Group != "" {
		db = db.Group(s.Group)
	}

	// 设置分页
	if s.IsPage {
		db = db.Limit(s.GetLimit()).Offset(s.GetOffset())
	}

}

// AddWhere 添加 and where条件
func (s *SqlBuilder) AddWhere(where string, params ...interface{}) {
	if s.Where == "" {
		s.Where = where
	} else {
		s.Where = fmt.Sprintf(" %s AND %s ", s.Where, where)
	}

	if len(params) > 0 {
		for _, v := range params {
			s.WhereParam = append(s.WhereParam, v)
		}
	}
}

// OrWhere 添加 or where条件
func (s *SqlBuilder) OrWhere(where string, params ...interface{}) {
	if s.Where == "" {
		s.Where = where
	} else {
		s.Where = fmt.Sprintf(" %s OR %s ", s.Where, where)
	}

	if len(params) > 0 {
		for _, v := range params {
			s.WhereParam = append(s.WhereParam, v)
		}
	}
}

// GetOne 获取一条数据
func (s *SqlBuilder) GetOne(ctx context.Context, res interface{}) error {
	s.Limit = 1
	s.Build()
	return s.DB.Find(res).Error
}

// GetList 获取列表
func (s *SqlBuilder) GetList(ctx context.Context, res interface{}) error {
	s.Build()
	return s.DB.WithContext(ctx).Find(res).Error
}

// GetCount 获取总数
func (s *SqlBuilder) GetCount(ctx context.Context) (int64, error) {
	s.Build()
	var res int64
	err := s.DB.WithContext(ctx).Count(&res).Error
	if err != nil {
		return 0, err
	}
	return res, nil
}
